﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LED_Editor.Model;
using System.ComponentModel;
using System.IO.Ports;
using LED_Editor.Config;
using LED_Editor.Properties;
using LED_Editor.Controls;
using System.Drawing;
using System.Windows.Forms;

namespace LED_Editor.ControllerProgramming {
	public class ControllerManager : Timer {
		public ControllerManager() {
			_controllers = new Dictionary<int, Controller>();
			_previewControllers = new Dictionary<int, LedPreviewComponent>();
			Interval = 50;
		}


		public SerialPort SerialPort { get; set; }

		private Dictionary<int, Controller> _controllers;
		private IContainer components;
		private Dictionary<int, LedPreviewComponent> _previewControllers;



		public Controller GetControllerByTrack(Track track) {
			Controller controller = null;
			if (_controllers.ContainsKey(track.UniqueId)) {
				controller = _controllers[track.UniqueId];
			} else {
				controller = new Controller(SerialPort);
				controller.Address = (byte)track.Id;
				_controllers.Add(track.UniqueId, controller);
			}
			controller.Address = (byte)track.Id;

			//if (track.Changed)
			//{
			List<Frame> frames2Convert = track.Frames.List.OfType<Frame>().ToList<Frame>();
			int maxDuration = MaxControllerDurationMilliseconds / 10;
			Frame syncFrame = GetSyncronizationFrame(track.TotalFramesDuration, maxDuration);
			if (!(syncFrame is EmptyFrame)) {
				syncFrame.TrackId = track.Id;
				frames2Convert.Add(syncFrame);
			}

			IEnumerable<FrameStruct> converted = FramesConverter.Instance.Convert(frames2Convert);

			controller.SetFrames(converted);
			track.Changed = false;
			//}
			controller.SetBaudRate(LED_Editor.Config.LedEditorConfig.Local.BaudRate);
			controller.SetPortName(LED_Editor.Config.LedEditorConfig.Local.PortName);
			return controller;
		}


		internal Frame GetSyncronizationFrame(int currentDuration, int maxDuration) {
			//Frame lastSyncronizationFrame       = Frame.CreateInstance ();
			//lastSyncronizationFrame.StartMarker = maxDuration;
			//lastSyncronizationFrame.EndMarker   = maxDuration;
			//lastSyncronizationFrame.FrameDuration = 0;

			//lastSyncronizationFrame.StartColor = Color.FromArgb(0, 0, 0, 0);
			//lastSyncronizationFrame.EndColor = Color.FromArgb(0, 0, 0, 0);

			//return lastSyncronizationFrame;
			return Frame.GetSyncronizationFrame(currentDuration, maxDuration);
		}

		public int MaxControllerDurationMilliseconds {
			get;
			set;
		}


		internal System.Drawing.Color GetColor(Track track, double milliseconds) {
			Controller controller = GetControllerByTrack(track);
			if (controller == null)
				return Color.Empty;


			LedPreviewComponent component = null;
			_previewControllers.TryGetValue(track.UniqueId, out component);
			if (component == null) {
				component = new LedPreviewComponent();
				component.Controller = controller;
				_previewControllers.Add(track.UniqueId, component);
			}


			Color color = component.GetColorByElapsedMilliseconds(milliseconds);
			return color;
		}

		private int _timerMilliseconds;

		public int TimerMilliseconds {
			get { return _timerMilliseconds; }
			set {

				_timerMilliseconds = value;
				if (_timerMilliseconds < 0) {
					_timerMilliseconds = 0;
				}
				if (_timerMilliseconds > MaxControllerDurationMilliseconds) {
					_timerMilliseconds = MaxControllerDurationMilliseconds;
				}
			}
		}

		protected override void OnTick(EventArgs e) {
			if (TimerMilliseconds == MaxControllerDurationMilliseconds) {
				TimerMilliseconds = 0;
			}
			TimerMilliseconds += this.Interval;
			base.OnTick(e);
		}

		private void InitializeComponent() {
			// 
			// ControllerManager
			// 
			this.Interval = 10;

		}
	}
}
